import { defineComponent, onMounted, ref, watch } from "vue";
import { tagPopoverProps } from "./tag-popover-types";
import TitanHighlight from "@/components/high-light/src/index";

/**
 * 计算字符占用html中的长度
 * @param str
 * @param font_size
 * @param font_family
 */
const getLenPx = (str: string, font_size: number, font_family = "Inter") => {
  let canvas: HTMLCanvasElement | null;
  let ctx: CanvasRenderingContext2D | null;
  canvas = document.createElement("canvas");
  ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
  ctx.font = `${font_size}px ${font_family}`;
  const metrics = ctx.measureText(str);
  canvas = null;
  ctx = null;
  return Math.ceil(metrics.width);
};

const padding = 8,
  margin = 5,
  border = 1;

const fontSize = 12;

export default defineComponent({
  name: "TitanTagPopover",
  props: tagPopoverProps,
  setup(props) {
    const refTag = ref<HTMLElement>();

    const visibleData = ref<{ label: string; width: number }[]>([]);
    const popoverData = ref<string[]>([]);

    const tmpData: { label: string; width: number }[] = [];

    const delWidth = () => {
      if (!props.data || !props.data.length) {
        return;
      }
      tmpData.length = 0;
      const warpWidth = (refTag.value?.offsetWidth || 0) - 24;
      let w = 0;
      const boxWidth = padding * 2 + border * 2 + margin;
      let showTagIndex = props.data?.length || 0;
      for (let i = 0; i < props.data?.length || 0; i++) {
        const t = getLenPx(props.data[i], fontSize) + boxWidth;
        w += t;
        if (w >= warpWidth) {
          if (!tmpData.length) {
            showTagIndex = i;
            tmpData.push({ label: props.data[i], width: t });
          }
          // 如果data的长度超过1， 如果处理上一个
          break;
        } else {
          // 如果总长度没有超过则加入展示列表
          showTagIndex = i;
          tmpData.push({ label: props.data[i], width: t });
        }
      }

      const _width = tmpData.slice(0, tmpData.length - 1).reduce((total, item) => total + item.width, 0);
      if (_width + tmpData[tmpData.length - 1].width > warpWidth) {
        tmpData[tmpData.length - 1].width = warpWidth - _width;
      }

      visibleData.value = tmpData.map((item) => ({
        ...item,
        width: item.width - margin,
      }));
      popoverData.value = props.data.slice(showTagIndex + 1, props.data.length);
    };

    onMounted(() => {
      delWidth();
    });

    watch(
      () => props.data,
      () => {
        delWidth();
      },
      { deep: true }
    );

    const renderTags = (item: string, needWidth = false, width = 0) => {
      const highlightOptions = props.highlightOptions;
      return (
        <a-tag style={needWidth ? { width: width + "px", marginRight: "5px" } : { marginRight: "5px" }}>
          {Object.keys(highlightOptions).length ? (
            <div class={needWidth && "ellipsis"}>
              <TitanHighlight
                {...highlightOptions}
                content={item}
              />
            </div>
          ) : (
            <div class={needWidth && "ellipsis"}>{item}</div>
          )}
        </a-tag>
      );
    };

    const popoverOptions = {
      position: "right",
      trigger: "hover",
      "content-class": "titan-tag-popover__popover",
    };
    Object.assign(popoverOptions, props.popover);

    return () => {
      let t = null;
      const visibleEl = visibleData.value.map((item) => renderTags(item.label, true, item.width));
      const popoverEl = (props.data || []).map((item) => renderTags(item));
      if (popoverData.value.length) {
        const reference = [
          <a-tag
            class="cursor"
            style={{ width: "24px" }}
          >
            ...
          </a-tag>,
        ];
        const slots = {
          content: () => popoverEl,
          default: () => reference,
        };
        t = (
          <a-popover
            v-slots={slots}
            {...popoverOptions}
          ></a-popover>
        );
      }
      return (
        <div
          class="titan-tag-popover"
          ref={refTag}
        >
          {visibleEl}
          {t}
        </div>
      );
    };
  },
});
